import WebSocket = require("ws");
import { SendDataType } from "./defines";
import { PlayerData } from "./PlayerData";

const MAX_PLAYER = 2;

type FrameData = {
  [frameCount: number]: { [id: number]: any };
};

export class Game {
  private clientStatesMap = new Map<WebSocket, PlayerData>();

  private frameCount = -1;

  private frameData: FrameData = {};

  private intervalId: NodeJS.Timeout;
  private client1: WebSocket;
  private client2: WebSocket;

  constructor(
    private client1Data: PlayerData,
    private client2Data: PlayerData
  ) {
    this.client1 = this.client1Data.ws;
    this.client2 = this.client2Data.ws;

    this.clientStatesMap.set(client1Data.ws, client1Data);
    this.clientStatesMap.set(client2Data.ws, client2Data);

    // 游戏开始前发送随机种子
    this.sendInitData();
  }

  /**
   * 确认收到消息
   * @param client
   */
  confirmData(client: WebSocket) {
    this.clientStatesMap.get(client).ready = true;
    let readyCount = 0;
    for (let item of this.clientStatesMap) {
      if (item[1].ready) {
        readyCount++;
      }
    }

    if (readyCount >= MAX_PLAYER) {
      this.sendStartGame();
      this.startGame();
    }
  }

  startGame() {
    this.intervalId = setInterval(this.update, 16.7);
    // this.intervalId = setInterval(this.update, 3000);
  }

  /**
   * 帧循环
   */
  update = () => {
    this.frameCount++;
    const { frameData, frameCount } = this;
    frameData[frameCount] = {};
    if (frameCount % 2 === 0 && frameCount !== 0) {
      const f1 = frameCount - 1;
      const f2 = frameCount - 2;

      const sendData = { [f1]: frameData[f1], [f2]: frameData[f2] };
      this.sendMessage(SendDataType.FrameData, sendData);
    }
  };

  /**
   * 收到操作数据
   * @param ws
   */
  receiveOperationData(ws: WebSocket, data: any) {
    const id = this.clientStatesMap.get(ws).id;
    const currentFrameData = this.frameData[this.frameCount];
    if (!currentFrameData[id]) {
      currentFrameData[id] = {};
    }
    const currentIdData = currentFrameData[id];
    Object.assign(currentIdData, data);
  }

  /**
   * 游戏结束
   */
  gameEnd(type: number) {
    clearInterval(this.intervalId);
    this.clientStatesMap = null;
    this.client1.emit("game-end");
    this.client2.emit("game-end");
  }

  /**
   * 发送初始化数据
   */
  private sendInitData() {
    const randomSeeds = new Array(100000);
    for (let i = 0; i < 100000; i++) {
      randomSeeds[i] = Math.random();
    }
    this.client1.send(
      JSON.stringify({
        type: SendDataType.GameCreated,
        data: {
          randomSeeds,
          playersData: [
            this.client1Data.toInitData(),
            this.client2Data.toInitData(),
          ],
        },
      })
    );
    this.client2.send(
      JSON.stringify({
        type: SendDataType.GameCreated,
        data: {
          randomSeeds,
          playersData: [
            this.client2Data.toInitData(),
            this.client1Data.toInitData(),
          ],
        },
      })
    );
  }

  /**
   * 发送开始游戏消息
   */
  private sendStartGame() {
    this.sendMessage(SendDataType.GameStart);
  }

  private sendMessage(type: SendDataType, data?: any) {
    if (this.client1.readyState === WebSocket.OPEN) {
      this.client1.send(JSON.stringify({ type, data }));
    }
    if (this.client2.readyState === WebSocket.OPEN) {
      this.client2.send(JSON.stringify({ type, data }));
    }
  }
}
